package jMiiEditor.gui.checker;

import jMiiEditor.mii.checker.MiiChecker;
import jMiiEditor.mii.checker.MiiCheckerProposal;
import jMiiEditor.mii.checker.MiiCheckerProposalAction;
import java.awt.Color;
import java.awt.Component;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

import com.googlecode.cchlib.i18n.AutoI18nCustomInterface;
import com.googlecode.cchlib.i18n.I18nInterface;

public class MiiCheckerTableModel
    extends AbstractTableModel
        implements TableModelListener,
                   AutoI18nCustomInterface
{
    private static final long serialVersionUID = 1L;
    /** @serial */
    private List<MiiCheckerProposal> checkResult;
    /** @serial */
    private List<String>  checkResultNewValue;
    /** @serial */
    private String[]      columnNames  = {
                            "Comment",
                            "DoIt",
                            "Action",
                            "Use custom value"
                            };
    /** @serial */
    private final String keyPrefix = getClass().getName() + ".";

    /**
     *
     * @param miiChecker
     */
    public MiiCheckerTableModel(
            MiiChecker  miiChecker
            )
    {
        super();

        this.checkResult = miiChecker.getMiiCheckerResults();
        final int size   = checkResult.size();
        this.checkResultNewValue = new ArrayList<String>(size);

        for(int i=0;i<size;i++) {
            MiiCheckerProposal rowValue = this.checkResult.get( i );

            if( rowValue instanceof MiiCheckerProposalAction) {
                String paramStringValue = MiiCheckerProposalAction.class.cast(rowValue).getParameterString();

                if( paramStringValue == null ) {
                    paramStringValue = ""; // Edition not supported
                }
                this.checkResultNewValue.add( paramStringValue );
                }
            else {
                this.checkResultNewValue.add( "" );
            }
        }

        addTableModelListener(this);
    }

    @Override
    public String getColumnName(int column)
    {
        return this.columnNames[column];
    }
    @Override
    public Class<?> getColumnClass(int columnIndex)
    {
        switch( columnIndex ) {
            case 1 : return Boolean.class;
            default: return String.class;
        }
    }

    @Override
    public int getColumnCount()
    {
        return this.columnNames.length;
    }

    @Override
    public int getRowCount()
    {
        return this.checkResult.size();
    }

    @Override
    public Object getValueAt( int row, int column )
    {
        try {
            MiiCheckerProposal rowValue = this.checkResult.get( row );

            switch( column ) {
                case 0 : return rowValue.getMessage();
                case 1 : //return this.checkResultDoIt.get( row );
                    if( rowValue instanceof MiiCheckerProposalAction ) {
                        return MiiCheckerProposalAction.class.cast( rowValue).isSelected();
                    }
                    else {
                        return false;
                    }
                case 2 : return rowValue.getMessageAction();
                case 3 : return this.checkResultNewValue.get( row );
                default: return null;
            }
       }
        catch( IndexOutOfBoundsException empty ) {
            // Table is empty !
            return null;
        }
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex)
    {
        if( columnIndex == 1 || columnIndex == 3 ) {
            MiiCheckerProposal rowValue = this.checkResult.get( rowIndex );

            if( rowValue instanceof MiiCheckerProposalAction ) {

                if( columnIndex == 3 ) {
                    if( MiiCheckerProposalAction.class.cast( rowValue ).getParameterString() == null ) {
                        return false;
                    }
                }

                return true;
            }
        }

        return false;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex)
    {
        //System.out.println( "setValueAt:" + aValue + " row:" + rowIndex + " col:" + columnIndex);
        if( columnIndex == 1 ) {
            MiiCheckerProposal rowValue = this.checkResult.get( rowIndex );

            if( rowValue instanceof MiiCheckerProposalAction ) {
                MiiCheckerProposalAction.class.cast( rowValue ).setSelected(
                                Boolean.class.cast( aValue )
                                );
            }
        }
        else if( columnIndex == 3 ) {
            MiiCheckerProposal rowValue = this.checkResult.get( rowIndex );

            if( rowValue instanceof MiiCheckerProposalAction ) {
                MiiCheckerProposalAction action = MiiCheckerProposalAction.class.cast( rowValue );

                String  str = String.class.cast( aValue );
                boolean res = action.setParameterString( str );

                if( !res ) {
                    Toolkit.getDefaultToolkit().beep();
                }

                this.checkResultNewValue.set( rowIndex, action.getParameterString() );
                super.fireTableDataChanged();
            }
        }
    }


    public void setColumnWidth(JTable table)
    {//Not Override
        TableColumn column = null;
        final int   count  = getColumnCount();

        for( int i = 0; i < count; i++ ) {
            column = table.getColumnModel().getColumn( i );
            switch( i ) {
                case 0:
                    column.setPreferredWidth( 300 );
                    break;
                case 1:
                    column.setPreferredWidth( 25 );
                    break;
                case 2:
                    column.setPreferredWidth( 200 );
                    break;
                case 3:
                    column.setPreferredWidth( 100 );
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void tableChanged( TableModelEvent event )
    {
        //super.tableChanged( event );
        int row    = event.getFirstRow();
        int column = event.getColumn();
        TableModel model = (TableModel)event.getSource();
        //String columnName = model.getColumnName(column);
        Object data = model.getValueAt(row, column);

        System.out.println( "tableChanged1:" + row + "," + column );

        if( data != null ) {
            System.out.println( "tableChanged2:" + data.getClass() );
        }
    }

    public void purgeMiiCheckerResultList()
    {//Not Override
        for( int i = checkResult.size()-1; i>=0; --i ) {
            MiiCheckerProposal mp = checkResult.get( i );
            boolean isSelected = false;

            if( mp instanceof MiiCheckerProposalAction ) {
                isSelected = MiiCheckerProposalAction.class.cast( mp ).isSelected();
            }

            if( ! isSelected ) {
                checkResult.remove( i );
                checkResultNewValue.remove( i );
            }
        }
    }

    public void clearMiiCheckerResultList()
    {
        checkResult.clear();
        checkResultNewValue.clear();
    }

    @Override
    public void setI18n( I18nInterface i18n )
    {
        for(int i =0;i<this.columnNames.length;i++) {
            this.columnNames[ i ] = i18n.getString( keyPrefix + i );
        }
        //TODO: refresh column names?
    }

    @Override
    public Map<String, String> getI18n( I18nInterface i18n )
    {
        Map<String,String> map = new HashMap<String,String>();

        for(int i =0;i<this.columnNames.length;i++) {
            map.put( keyPrefix + i, this.columnNames[ i ] );
        }

        return map;
    }

    public JTable getJTable()
    {
        return new JTable(MiiCheckerTableModel.this)
        {
            private static final long serialVersionUID = 1L;
            final MyCheckBox myCheckBox = new MyCheckBox();
            final MyJLabel   myJLabel   = new MyJLabel();

            @Override
            public TableCellRenderer getCellRenderer(int row, int column)
            {
                if( column == 1 ) {
                    return myCheckBox;
                }
                else if( column == 3 ) {
                    return myJLabel;
                }

                return super.getCellRenderer(row, column);
            }

            class MyCheckBox extends JCheckBox implements TableCellRenderer
            {
                private static final long serialVersionUID = 1L;

                @Override
                public Component getTableCellRendererComponent(
                        JTable  table,
                        Object  value,
                        boolean isSelected,
                        boolean hasFocus,
                        int     row,
                        int     column
                        )
                {
                    //NOTE: Lost Background color,
                    //      not nice on LookAndFeel witch use
                    //      different color for odd and pair lines
                    if( column == 1 ) {
                        MiiCheckerProposal rowValue  = MiiCheckerTableModel.this.checkResult.get( row );
                        boolean checkbIsSelected;
                        boolean checkbIsEnabled;

                        if( rowValue instanceof MiiCheckerProposalAction ) {
                            checkbIsSelected = MiiCheckerProposalAction.class.cast( rowValue).isSelected();
                            checkbIsEnabled = true;
                            //setBackground( Color.WHITE );
                        }
                        else {
                            checkbIsSelected = false;
                            checkbIsEnabled = false;
                            //setBackground( Color.GRAY );
                        }
                        setSelected( checkbIsSelected );
                        setEnabled( checkbIsEnabled );
                    }
                    return this;
                }
   // The following methods override the defaults for performance reasons
   @Override public void validate() {}
   @Override public void revalidate() {}
   @Override protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}
   @Override public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
            }

            class MyJLabel extends JLabel implements TableCellRenderer
            {
                private static final long serialVersionUID = 1L;

                @Override
                public Component getTableCellRendererComponent(
                        JTable  table,
                        Object  value,
                        boolean isSelected,
                        boolean hasFocus,
                        int     row,
                        int     column
                        )
                {
                    if( column == 3 ) {
                        MiiCheckerProposal rowValue  = MiiCheckerTableModel.this.checkResult.get( row );

                        setText(String.class.cast( value ));

                        if( rowValue instanceof MiiCheckerProposalAction) {
                            String paramStringValue = MiiCheckerProposalAction.class.cast(rowValue).getParameterString();

                            if( paramStringValue == null ) {
                                setForeground( Color.LIGHT_GRAY );
                            }
                            else {
                                setForeground( Color.GREEN );
                            }
                        }
                        else {
                            setForeground( Color.LIGHT_GRAY );
                        }
                    }
                    return this;
                }
   // The following methods override the defaults for performance reasons
   @Override public void validate() {}
   @Override public void revalidate() {}
   @Override protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}
   @Override public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
            }
        };
    }

}

/****
JTable table = new JTable();
// Add data...
// Install the custom header renderer on the first visible column
int vColIndex = 0;
TableColumn col = table.getColumnModel().getColumn(vColIndex);
col.setHeaderRenderer(new MyTableHeaderRenderer());

public class MyTableHeaderRenderer extends JLabel implements TableCellRenderer
{
    // This method is called each time a column header
    // using this renderer needs to be rendered.
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex)
    {
        // 'value' is column header value of column 'vColIndex'
        // rowIndex is always -1
        // isSelected is always false
        // hasFocus is always false
        // Configure the component with the specified value
        setText(value.toString());
        // Set tool tip if desired
        setToolTipText((String)value);
        // Since the renderer is a component,
        return itself return this;
   }

   // The following methods override the defaults for performance reasons
   public void validate() {}
   public void revalidate() {}
   protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}
   public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
}
**/
